Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

state/remote/s3: Fix Bug with Assume Role for Federated IAM Account #10067

Merged
merged 2 commits into from
Feb 9, 2017
Merged

state/remote/s3: Fix Bug with Assume Role for Federated IAM Account #10067

merged 2 commits into from
Feb 9, 2017

Conversation

darend
Copy link
Contributor

@darend darend commented Nov 11, 2016

what

Add missing role_arn parameter necessary for federated IAM accounts when using s3 for remote state. The attribute is named role_arn for consistency with AWS provider: https://www.terraform.io/docs/providers/aws/index.html#role_arn

usage

terraform remote config -backend=s3 \
  -backend-config="bucket=<bucket>" \
  -backend-config="key=<key>"  \
  -backend-config="region=$AWS_REGION" \
  -backend-config="profile=$AWS_PROFILE" \
  -backend-config="role_arn=arn:aws:iam::<account_id>:role/<Role>"

testing

I could not see a reasonable way to test this change. The call to get the credentials returns an aws Credential. This does not provide any means of inspecting its internals. Alternatively the s3Factory would need to support a way of mocking the GetCredentials call

why

Fixes #8739

@darend
Copy link
Contributor Author

darend commented Nov 11, 2016

It would be ideal if remote config AND the aws provider both supported an ENV flag for the role, akin to how AWS_PROFILE or AWS_SESSION_TOKEN can be used. This would eliminate the need to edit the provider or remote config when the role changes. Unfortunately AWS does not support an env flag for assume role.

I don't have a lot of familiarity with the code so I did not pursue it very far. But I could see how an env flag for the role could be enabled for remote config by having a section like this for it:

regionName, ok := conf["region"]
.

Similarly for the provider the assume_role config could be modified to support an env flag like this

DefaultFunc: schema.MultiEnvDefaultFunc([]string{

@darend
Copy link
Contributor Author

darend commented Nov 16, 2016

I identified a related issue where the s3 remote does not check for errors after obtaining the AWS credentials. This would lead to crashes
See https://github.com/hashicorp/terraform/pull/10067/files#diff-7bd4c7cfc297dcc74cb94a512b5cece5R71

@darend darend changed the title state/remote/s3: Add support for assume role state/remote/s3: Fix Bug with Assume Role for Federated IAM Account Dec 13, 2016
@darend
Copy link
Contributor Author

darend commented Dec 13, 2016

@stack72 I do not see this as an enhancement, but a critical bug fix in order to support federated IAM accounts with remote state. It’s critical because without it, it’s not possible to use use multiple AWS accounts with federated logins, which is the best practice for securing AWS environments

@benjdlambert
Copy link

👍

Daren Desjardins added 2 commits January 26, 2017 11:29
@shinofara
Copy link

+1

@michelvocks
Copy link

Really looking forward to this feature/bug fix :-)

@beneshed
Copy link

beneshed commented Feb 8, 2017

+1

Copy link
Contributor

@jen20 jen20 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, this was overlooked at the original time assume role functionality was added.

@stack72
Copy link
Contributor

stack72 commented Feb 9, 2017

@darend after speaking with @jen20 on this - we agree this is good to merge :) There is no straight forward way to test but we can verify this locally

@stack72 stack72 merged commit 5718294 into hashicorp:master Feb 9, 2017
@jen20
Copy link
Contributor

jen20 commented Feb 9, 2017

@stack72, one thing I think we should add is an errwrap.Wrapf around the newly returned error so the provenance is more obvious.

stack72 pushed a commit that referenced this pull request Feb 9, 2017
…10067)

* Enable remote s3 state support for assume role

- provide role_arn in backend config to enable assume role

Fixes #8739

* Check for errors after obtaining credentials
@darend
Copy link
Contributor Author

darend commented Feb 9, 2017

@darend after speaking with @jen20 on this - we agree this is good to merge :) There is no straight forward way to test but we can verify this locally

Thanks!

@jtopper
Copy link
Contributor

jtopper commented Feb 11, 2017

I've been trying this out since it merged - it looks like this works for initial remote state configuration, but the role_arn key doesn't get written as config into the local state file - as such, subsequent runs of terraform commands fail to assume the role before accessing the remote state.

@jtopper
Copy link
Contributor

jtopper commented Feb 11, 2017

Update: actually the failure case I mentioned above only holds if there's already a remote state in place without the role_arn config key.

@jen20
Copy link
Contributor

jen20 commented Feb 11, 2017

@jtopper that's a bug - did you just run remote config again?

@jtopper
Copy link
Contributor

jtopper commented Feb 11, 2017

I had an existing set of remote state, and ran remote config specifying a role_arn this time. That command completed as expected, but the local copy of the state file didn't have a role arn key in it.

Since I'm hacking on an empty account, I deleted the S3 copy and the local state file, and ran remote config again with a role_arn, after which everything behaves as expected.

@frank-bee
Copy link

I tried to configure remote state from an ec2 which uses the instance profile mechanism. Allways get access denied. Anyone facing the same problem?

@bacoboy
Copy link

bacoboy commented Feb 20, 2017

I was having an issue, but realized I was still using 0.8.6. After upgrading to 0.8.7, I can confirm it is working.

@bnf2si take a look at your trust profile. By default an EC2 IAM role just has the ec2 service listed as "trusted" in the "trust relationship" tab. To make this works you need to do 2 things:

  1. grant your EC2 box the AssumeRole permission for the specific role as in this example:
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::YOUR_ACCOUNT:role/Admin"
    }
}

But then you need to also add a trust policy to the target role (in this example role/Admin) to the source principal. The easiest way to do this is with a cross account role (but using your own account) in the Trust Relationship:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::YOUR_ACCOUNT:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Hope this helps.

@frank-bee
Copy link

frank-bee commented Feb 20, 2017

I also found a solution now for my usecase.
I wanted use the same terraform files for access from a) federated account access and b) from an EC2 via profile

With the following assume role configuration in my terraform files I had to attach a policy to "JenkinsAgentCreator" role to allow assuming itself , otherwise I cannot run from terraform from an EC2 via profile.
Proposal: Terraform should recognize that it runs from an EC2 via profile and in this case not assuming the role because it is already assumed somehow.

My example code

provider "aws" {
  region = "${var.aws_region}"
  insecure = "${var.insecure}"
  allowed_account_ids = ["${var.account_id}"] // allow only to do things in sample account, nowhere else

  assume_role {
    role_arn = "arn:aws:iam::${var.account_id}:role/JenkinsAgentCreator"
    session_name = "creating_jenkins_agents"
  }
}

data "terraform_remote_state" "agents" {
    backend = "s3"
    config {
        bucket = "terraform-state-eclipseprojects.etas-dev.com"
        key = "agents_golden_ami/terraform.tfstate"
        region = "eu-central-1"
        encrypt = "true"
        role_arn = "arn:aws:iam::${var.account_id}:role/JenkinsAgentCreator"
    }
} 

@benrobinsonsonos
Copy link

Problem: Running Terraform from an EC2 instance with an instance profile that allows assuming roles, Terraform can assume another role in the AWS provider block, however, cannot assume another role for remote config using S3 backend with the "role_arn" configuration variable.

Workaround: Script that performs an STS assume role (assumes that assumed role has the appropriate s3 privileges), script disables remote config, script reenables remote config with the STS temporary credentials.

Note: Terraform will complain when the credentials expire.

"Error reloading remote state: ExpiredToken: The provided token has expired."

Rerun the script. Run Terraform.

@ghost
Copy link

ghost commented Apr 16, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for AWS assume roles when configuring S3 remote state storage